package cn.wilson.hrm.service.impl;

import cn.wilson.hrm.dto.SendSmsDTO;
import cn.wilson.hrm.feign.client.RedisFeignClient;
import cn.wilson.hrm.service.IVerifyCodeService;
import cn.wilson.hrm.utils.AjaxResult;
import cn.wilson.hrm.utils.HttpUtil;
import cn.wilson.hrm.utils.StrUtils;
import cn.wilson.hrm.utils.VerifyCodeUtils;
import cn.wilson.hrm.vo.SendSmsCodeVo;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    //读取配置中属性
    @Value("${usercenter.imageCode.length}")
    private int imageCodeLength = 4;

    //图片验证码key过期时间
    @Value("${usercenter.imageCode.timeout}")
    private int timeout = 300;

    //图片的宽度
    @Value("${usercenter.imageCode.width}")
    private int width = 140;

    //图片的高度
    @Value("${usercenter.imageCode.height}")
    private int height = 5;

    //手机验证码的长度
    @Value("${usercenter.imageCode.mobileLength}")
    private int mobileLength = 4;

    @Autowired
    private RedisFeignClient redisFeignClient;


    @Override
    public String createImageCode(String imageKey) {
        //参数判断
        if (StringUtils.isBlank(imageKey)){
            //如果你是空的我就抛异常
            throw new RuntimeException("前端传入的验证码key无效");
        }

        //后端接收到imageKey，后端要生成图片验证码的值  4位
        String imageValue = UUID.randomUUID().toString().substring(0,imageCodeLength);

        //把图片验证码的值存储到redis中  以前端传入的key去存   设置过期时间
        AjaxResult imageCodeResult = redisFeignClient.setex(imageKey, timeout, imageValue);
        //判断是否存进去了
        if (!imageCodeResult.isSuccess()){
            //如果没有存进去
            throw new RuntimeException("图片创建失败");
        }

        //把图片验证码的值合并到一个图片   base64编码后的图片字符串
        String imageBase64Str = VerifyCodeUtils.verifyCode(width, height, imageValue);

        //把图片基于base64编码成字符串响应给页面
        return imageBase64Str;
    }

    @Override
    public void sendSmsCode(SendSmsDTO sendSmsDTO) {
        //基本参数判断
        //图片验证码
        String imageCode = sendSmsDTO.getImageCode();
        //手机号
        String mobile = sendSmsDTO.getMobile();
        //图片验证码的key
        String imageCodeKey = sendSmsDTO.getImageCodeKey();
        if (StringUtils.isBlank(imageCodeKey) || StringUtils.isBlank(imageCode) || StringUtils.isBlank(mobile)){
            throw new RuntimeException("无效的图片验证码或手机验证码");
        }
        //后端判断图片验证码是否正确 redis中的值和传入的进行比较
        AjaxResult ajaxResult = redisFeignClient.get(imageCodeKey);
        if (!ajaxResult.isSuccess() || ajaxResult.getResultObj() == null){
            throw new RuntimeException("无效的图片验证码，请重新填写");
        }
        //获取redis中的图片验证码
        String imageCodeFromRedis = ajaxResult.getResultObj().toString();
        if (!imageCodeFromRedis.toLowerCase().equals(imageCode.toLowerCase())){
            throw new RuntimeException("图片验证码错误");
        }



        //存入redis中的key通过前缀加手机号
        String smsCodeKey = "REGISTER:SMS:" + mobile;
        //当前时间
        Date now = new Date();
        //全局定义个短信验证码
        String smsCodeValue = null;

        //后端判断redis中是否已经有了一个有效的验证码  上一次的验证码last
        AjaxResult lastSmsCodeResult = redisFeignClient.get(smsCodeKey);
        //说明上一次有东西  redis中有值
        if (lastSmsCodeResult.isSuccess() && lastSmsCodeResult.getResultObj() != null){
            //获取redis中的发送记录
            //先拿出来  存的时候是以SendSmsCodeVo对象的json去存的，拿出来我们需要处理一下
            String lastSendSmsCodeVoJson = lastSmsCodeResult.getResultObj().toString();   //此时得到的是json字符串

            //将json字符串转成SendSmsCodeVo对象
            SendSmsCodeVo sendSmsCodeVo = JSON.parseObject(lastSendSmsCodeVoJson, SendSmsCodeVo.class);

            //判断上一次发送时间和这一次发送的时间差是否超过了60s
            // 没有超过就不要创建新的验证码
            //获取上一次发送的时间
            Date lastSendTime = sendSmsCodeVo.getSendTime();

            //getTime()获取时间的毫秒值， /1000 ：秒   小于60秒
            if ((now.getTime() - lastSendTime.getTime())/1000 < 60){
                throw new RuntimeException("短信发送频繁，请稍后再试");
            }

            //，把上一次的验证码重新发一下，
            smsCodeValue = sendSmsCodeVo.getSmsCode();

            //然后把发送时间重置
        }else {
            //如果redis中没有的话，需要从新生成一个新的验证码
            smsCodeValue = StrUtils.getRandomString(mobileLength);
        }




        //把手机验证码发送记录存储到redis中，手机号，验证码，发送时间，redis的key
        //把验证码发送记录封装成对象
        SendSmsCodeVo sendSmsCodeVo = new SendSmsCodeVo(smsCodeValue,now);
        //把对象转成json存储到redis
        String sendSmsCodeVoJson = JSON.toJSONString(sendSmsCodeVo);
        AjaxResult sendResult = redisFeignClient.setex(smsCodeKey, timeout, sendSmsCodeVoJson);
        //判断是否设置到redis中去了
        if (!sendResult.isSuccess()){
            throw new RuntimeException("验证码发送失败");
        }



        //把验证码的内容进行发送到用户的手机  短信网关
        String message = "您的手机验证码为["+smsCodeValue+"],请在5分钟内使用";
        System.out.println(message);

        HashMap<String, String> params = new HashMap<>();
        params.put("Uid", "LQS18782870626");
        params.put("Key", "d41d8cd98f00b204e980");
        params.put("smsMob",mobile);
        params.put("smsText",message);
        HttpUtil.sendPost("http://utf8.api.smschinese.cn/", params);
    }
}
